package com.example.common.plugins.authentication;

import cn.hutool.core.util.ObjUtil;
import com.example.starter.util.ExceptionUtil;
import com.example.starter.util.Response;
import com.example.starter.weixin.pojo.WxSession;
import com.example.starter.weixin.util.WxUtil;
import com.example.system.api.WeixinApi;
import com.example.system.dto.WeixinExtraDto;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;

/**
 * @author 王令
 * @since 2022/12/1 21:57
 */
@Setter
public class WeixinLoginAuthenticationProvider implements AuthenticationProvider {

    private MobileUserDetailService mobileUserDetailService;
    private WeixinApi weixinApi;

    @Value("${com.example.weixin.appid}")
    private String appid;
    @Value("${com.example.weixin.secret}")
    private String secret;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        final WeixinLoginAuthenticationToken
                authenticationToken = (WeixinLoginAuthenticationToken) authentication;
        final String mobile = (String) authenticationToken.getPrincipal();
        final String js_code = (String) authenticationToken.getCredentials();
        final UserDetails user = mobileUserDetailService.loadUserByMobile(mobile);
        if (user == null) {
            throw new InternalAuthenticationServiceException("用户不存在");
        }
        WxSession wxSession = WxUtil.login(appid, secret, js_code);
        if (ObjUtil.equals(wxSession.getErrcode(), 40029)) {
            throw ExceptionUtil.wrap("code 无效");
        }
        if (ObjUtil.equals(wxSession.getErrcode(), 45011)) {
            throw ExceptionUtil.wrap("api minute-quota reach limit  mustslower  retry next minute");
        }
        if (ObjUtil.equals(wxSession.getErrcode(), 40226)) {
            throw ExceptionUtil.wrap("code blocked");
        }
        if (ObjUtil.equals(wxSession.getErrcode(), -1)) {
            throw ExceptionUtil.wrap("system error");
        }

        Response<WeixinExtraDto> response = weixinApi.loadWeixinExtra(user.getUsername());
        if (response.isOk() && ObjUtil.isNull(response.getData())) {
            WeixinExtraDto extra = new WeixinExtraDto();
            extra.setUsername(user.getUsername());
            extra.setOpenid(wxSession.getOpenid());
            extra.setUnionid(wxSession.getUnionid());
            weixinApi.saveWeixinExtra(extra);
        }

        final WeixinLoginAuthenticationToken
                authenticationTokenResult = new WeixinLoginAuthenticationToken(user, js_code, user.getAuthorities());
        authenticationTokenResult.setDetails(authenticationToken.getDetails());
        return authenticationTokenResult;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return WeixinLoginAuthenticationToken.class.isAssignableFrom(authentication);
    }

}
